package ckw.gui;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;

import ckw.database.model.Election;
import ckw.database.model.ElectionNode;
import ckw.database.model.Node;

public class WzdPgAddEditElectionRKWs extends ModelValidationWizardPage {

	private class RKWTableLabelProvider extends LabelProvider implements ITableLabelProvider {
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		public String getColumnText(Object element, int columnIndex) {
			return ((ElectionNode) element).getNode().getName();
		}
	}

	private static class RKWContentProvider implements IStructuredContentProvider {
		@SuppressWarnings("unchecked")
		public Object[] getElements(Object inputElement) {
			return ((List<ElectionNode>) inputElement).toArray();
		}

		public void dispose() {
		}

		@Override
		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
		}
	}

	private boolean addElection;
	private Election election;

	Map<Integer, ElectionNode> idToElectionNodeMap;

	private Table tblRKW;
	private CheckboxTableViewer chckbxTblVwr;

	/**
	 * Create the wizard.
	 */
	public WzdPgAddEditElectionRKWs(boolean addElection, Election election) {
		super("WzdPgAddEditElectionRKW");

		this.addElection = addElection;
		this.election = election;

		if (addElection) {
			setTitle("Add Elections RKWs");
		} else {
			setTitle("Edit Elections RKWs");
		}

		setDescription("Set Elections RKWs");
	}

	/**
	 * Create contents of the wizard.
	 * 
	 * @param parent
	 */
	public void createControl(Composite parent) {
		Composite cmpMain = new Composite(parent, SWT.NULL);

		setControl(cmpMain);
		cmpMain.setLayout(new GridLayout(1, false));

		chckbxTblVwr = CheckboxTableViewer.newCheckList(cmpMain, SWT.BORDER | SWT.FULL_SELECTION);
		chckbxTblVwr.setColumnProperties(new String[] {});
		tblRKW = chckbxTblVwr.getTable();
		tblRKW.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		chckbxTblVwr.setLabelProvider(new RKWTableLabelProvider());
		chckbxTblVwr.setContentProvider(new RKWContentProvider());

		initValues();
		setValidationListeners();
	}

	private void initValues() {
		idToElectionNodeMap = new HashMap<Integer, ElectionNode>();

		List<ElectionNode> checkedElectionNodes = new ArrayList<ElectionNode>();

		for (ElectionNode electionNode : election.getNodes()) {
			idToElectionNodeMap.put(electionNode.getNode().getId().intValue(), electionNode);
			checkedElectionNodes.add(electionNode);
		}

		for (Node node : manager.getAllRkwNodes()) {
			int nodeId = node.getId().intValue();

			if (idToElectionNodeMap.get(nodeId) == null) {
				ElectionNode electionNode = new ElectionNode();
				electionNode.setElection(election);
				electionNode.setNode(node);

				idToElectionNodeMap.put(electionNode.getNode().getId().intValue(), electionNode);
			}
		}

		election.setNodes(checkedElectionNodes);

		chckbxTblVwr.setInput(new ArrayList<ElectionNode>(idToElectionNodeMap.values()));

		if (addElection) {
			setPageComplete(false);
		} else {
			List<ElectionNode> checkedNodes = new ArrayList<ElectionNode>();
			for (ElectionNode electionNode : election.getNodes()) {
				checkedNodes.add(electionNode);
			}
			chckbxTblVwr.setCheckedElements(checkedNodes.toArray());
		}
	}

	private void setValidationListeners() {
		chckbxTblVwr.addCheckStateListener(new ICheckStateListener() {
			@Override
			public void checkStateChanged(CheckStateChangedEvent arg0) {
				validate();
				election.setNodes(getCheckedElectionNodes());
				updateVotersAndMembersWizardPage();
			}
		});
	}

	public List<ElectionNode> getCheckedElectionNodes() {
		Object[] checkedElements = chckbxTblVwr.getCheckedElements();
		ElectionNode[] electionNodes = Arrays.copyOf(checkedElements, checkedElements.length, ElectionNode[].class);
		List<ElectionNode> checkedNodes = new ArrayList<ElectionNode>(Arrays.asList(electionNodes));
		return checkedNodes;
	}

	private void updateVotersAndMembersWizardPage() {
		WzdAddEditElection wzdAddEditElection = (WzdAddEditElection) getWizard();
		wzdAddEditElection.getWzdPgAddEditElectionRKWMembers().refreshPage();
		wzdAddEditElection.getWzdPgAddEditElectionRKWMembers().validate();
		wzdAddEditElection.getWzdPgAddEditElectionRKWVoters().refreshPage();
		wzdAddEditElection.getWzdPgAddEditElectionRKWVoters().validate();
		wzdAddEditElection.getContainer().updateButtons();
	}

	@Override
	protected void validate() {
		if (MainWindow.isInDebugMode()) {
			clearErrorState();
			return;
		}

		// error
		if (getCheckedElectionNodes().isEmpty()) {
			setErrorState("Election must have at least one RKW.");
			return;
		}

		// ok
		clearErrorState();
	}

	@Override
	protected void update() {
	}
}
